package com.dolphin.common.utils;

import com.dolphin.common.component.var.model.BaseVarModel;
import com.dolphin.common.component.var.model.TimeWindowVarModel;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * @author shida
 */
@Slf4j
public class TypeUtils {

    public static String castToString(Object value){
        return value == null ? null : value.toString();
    }

    public static Double castToDouble(Object value){
        if(value == null){
            return null;
        } else if (value instanceof Number) {
            return ((Number) value).doubleValue();
        } else if (value instanceof String) {
            String strValue = value.toString();

            if (strValue.length() != 0 && !"null".equals(strValue) && !"NV".equals(strValue)) {
                if(strValue.indexOf(44) != 0){
                    strValue = strValue.replaceAll(",", "");
                }
                return Double.parseDouble(strValue);
            }else {
                return null;
            }
        }else {
            throw new RuntimeException("can not cast to double, value=" + value);
        }
    }

    public static Long castToLong(Object value){
        if(value == null){
            return null;
        } else if (value instanceof Number) {
            return ((Number) value).longValue();
        } else if (value instanceof String) {
            String strValue = value.toString();

            if (strValue.length() != 0 && !"null".equals(strValue) && !"NV".equals(strValue)) {
                if(strValue.indexOf(44) != 0){
                    strValue = strValue.replaceAll(",", "");
                }
               return Long.parseLong(strValue);
           }
       }

        return null;
    }

    private static Map<String, Object> castToMap(Object value){
        if(value instanceof String){
            return JsonInterface.jsonObject2Map((String)value);
        }

        if(value instanceof Map){
            Map<String, Object> tmpMap = (Map<String, Object>) value;
            return Maps.newLinkedHashMap(tmpMap);
        }

        return null;
    }

    public static Object cast(Object obj, BaseVarModel varModel){
        if(obj == null){
            return null;
        }

        try {
            if(obj instanceof Collection && varModel instanceof TimeWindowVarModel){
                Class elemClass = ((TimeWindowVarModel) varModel).getStatisticVarValueType().getClazz();
                Collection coll = (Collection) obj;
                List list = new ArrayList(coll.size());
                for(Object o : coll){
                    list.add(doCast(o, elemClass));
                }

                return list;
            }
            return doCast(obj, varModel.getValueType().getClazz());
        }catch (Exception e){
            log.error("cast value error, obj=" + obj, e);
        }

        return null;
    }

    public static Object cast(Object obj, Class clazz){
        try{
            return doCast(obj, clazz);
        }catch (Exception e){
            log.error("cast value error, obj=" + obj, e);
        }

        return null;
    }

    private static Object doCast(Object obj, Class clazz){
        if(obj == null){
            return null;
        }
        if(clazz == null){
            throw new IllegalArgumentException("class is null");
        }
        if(clazz == obj.getClass() || clazz.isAssignableFrom(obj.getClass())){
            return obj;
        }

        String strVal = obj.toString();
        if(strVal.length() == 0 || "null".equals(strVal) || "NV".equals(strVal)){
            return null;
        }

        if(clazz == String.class){
            return castToString(obj);
        }
        if(clazz == BigDecimal.class){
            return new BigDecimal(strVal.replaceAll(",", ""));
        }
        if(clazz == Integer.class){
            return Integer.valueOf(strVal.replaceAll(",", ""));
        }
        if(clazz == Long.class){
            return Long.valueOf(strVal.replaceAll(",", ""));
        }
        if(clazz == Double.class){
            return Double.valueOf(strVal.replaceAll(",", ""));
        }
        if(clazz == Float.class){
            return Float.valueOf(strVal.replaceAll(",", ""));
        }
        if(clazz == Short.class){
            return Short.valueOf(strVal.replaceAll(",", ""));
        }
        if(clazz == Byte.class){
            return Byte.valueOf(strVal.replaceAll(",", ""));
        }
        if (clazz == Boolean.class){
            if("true".equalsIgnoreCase(strVal) || "1".equalsIgnoreCase(strVal)){
                return Boolean.TRUE;
            }else if("false".equalsIgnoreCase(strVal) || "0".equalsIgnoreCase(strVal)){
                return Boolean.FALSE;
            } else if ("Y".equalsIgnoreCase(strVal) || "T".equalsIgnoreCase(strVal)) {
                return Boolean.TRUE;
            } else if ("F".equalsIgnoreCase(strVal) || "N".equalsIgnoreCase(strVal)) {
                return Boolean.FALSE;
            }
        }
        if(clazz == Map.class){
            return castToMap(obj);
        }

        throw new RuntimeException("can not cast to : " + clazz);

    }
}
